<script setup lang="ts">
import { ColumnsType } from 'ant-design-vue/es/table';
import { h } from 'vue'
const antIcons: any = inject('antIcons')
import { updateMenu, UpdateMenuRes, addMenu } from '@/api/security'
import { SysMenuTree, CrudBack } from '@/interface/user';
import { message } from 'ant-design-vue';
import {
  CheckOutlined,
  CloseOutlined
} from '@ant-design/icons-vue'
import { Key } from 'ant-design-vue/es/table/interface';
import { GetAdminMenuTreeRes, getAdminMenuTree, deleteMenuApi } from '@/api/security';
import IconOption from './iconOption'
import { Rule } from 'ant-design-vue/es/form';
import { SysMenu } from '@/interface/menu';
import { useGlobalStore } from '@/store/globalStore';

const columns: ColumnsType<any> = [
  {
    title: '菜单名称',
    dataIndex: 'menuName',
    key: 'menuName',
    ellipsis: true,
  },
  {
    title: '顺序',
    dataIndex: 'orderNum',
    key: 'orderNum',
    width: 60
  },
  {
    title: '图标',
    dataIndex: 'icon',
    key: 'icon',
    width: 60
  },
  {
    title: '路由地址',
    dataIndex: 'path',
    key: 'path',
    ellipsis: true,
  },
  {
    title: '路由组件',
    dataIndex: 'component',
    key: 'component',
  },
  {
    title: '创建时间',
    dataIndex: 'createTime',
    key: 'createTime',
  },
  {
    title: '状态',
    key: 'status',
    dataIndex: 'status',
  },
  {
    title: '操作',
    key: 'operation',
    fixed: 'right',
    width: 150,
  },
];

const data = ref<SysMenuTree[]>([])
const fatherMenu = ref<any>([
  {
    label: '主目录',
    value: 0,
    children: []
  }
])

const globalStore = useGlobalStore()

const contentBoxRef = ref<HTMLElement>()
const isLoading = ref<boolean>(false);
const editApiLoading = ref<boolean>(false);
const editPopShow = ref<boolean>(false);

const currEditData = reactive<SysMenuTree>({
  children: [],
  menuId: -1,
  menuName: '',
  name: '',
  parentId: -1,
  orderNum: 1000,
  path: '',
  component: '',
  query: '',
  isFrame: 0,
  isCache: 0,
  menuType: '',
  visible: '',
  status: '0',
  icon: '',
  createBy: '',
  createTime: '',
  updateBy: '',
  updateTime: '',
  menuPermPrefix: '',
  remark: '',
})

const getDatas = async (isSearch = false) => {
  isLoading.value = true;
  data.value = []
  if (isSearch) {
    return
  }
  try {
    const { data: res }: { data: GetAdminMenuTreeRes } = await getAdminMenuTree()
    //key用于选中操作
    data.value = dfsDeleteChildren(JSON.parse(JSON.stringify(res.data)))
    fatherMenu.value[0].children = genFatherSelectMenu(JSON.parse(JSON.stringify(res.data)))
  } catch (error) {
    console.error(error);
  } finally {
    isLoading.value = false;
  }
}

//构造可选的父级菜单
const genFatherSelectMenu = (data: SysMenuTree[]) => {
  return data.filter((item: SysMenuTree) => {
    item.label = item.menuName
    item.value = item.menuId as number
    if (item.children && item.children?.length !== 0) {
      item.children = genFatherSelectMenu(item.children as SysMenuTree[])
    }
    return item.menuType == 'M'
  })
}

const dfsDeleteChildren = (data: SysMenuTree[]) => {
  return data.map((item: SysMenuTree) => {
    if (item.children?.length === 0) {
      delete item.children
    } else {
      dfsDeleteChildren(item.children as SysMenuTree[])
    }
    return item
  })
}

const reloadData = () => {
  getDatas()
}

const deleteData = async (_e: MouseEvent, menuId: number) => {
  return new Promise((resolve) => {
    deleteMenuApi(menuId.toString()).then(res => {
      if (res.data.code == 200) {
        message.success('删除成功')
        reloadData()
      } else {
        message.error(res.data.msg || '删除失败')
      }
      resolve(true)
    }).catch((_err) => {
      resolve(true)
    })
  });
}

const deleteBatchData = async () => {
  deleteMenuApi(selectedRows.value.join(',')).then(res => {
    if (res.data.code == 200) {
      message.success('删除成功')
      selectedRows.value = []
    } else {
      message.error(res.data.msg || '删除失败')
    }
    getDatas()
  })
}

const handleEditOk = async () => {
  editApiLoading.value = true
  try {
    if (currEditData.menuType === 'M') {
      currEditData.menuPermPrefix = ''
    }
    const { data: res }: { data: UpdateMenuRes } = await updateMenu(currEditData)
    if (res.code == 200) {
      message.success('更新成功')
      getDatas()
      editPopShow.value = false
    } else {
      message.error(res.msg || '更新失败')
    }
  } catch (error) {

  } finally {
    editApiLoading.value = false
  }
}

const editData = (data: any) => {
  editPopShow.value = true
  const { children, menuId, menuName, name, parentId, orderNum, path, component, query, isFrame,
    isCache, menuType, visible, status, icon, createBy, createTime, updateBy, updateTime, remark, menuPermPrefix } = data
  currEditData.menuId = menuId
  currEditData.menuName = menuName
  currEditData.name = name
  currEditData.parentId = parentId
  currEditData.orderNum = orderNum
  currEditData.path = path
  currEditData.component = component
  currEditData.query = query
  currEditData.isFrame = isFrame
  currEditData.isCache = isCache
  currEditData.menuType = menuType
  currEditData.visible = visible
  currEditData.status = status
  currEditData.icon = icon
  currEditData.createBy = createBy
  currEditData.createTime = createTime
  currEditData.updateBy = updateBy
  currEditData.updateTime = updateTime
  currEditData.menuPermPrefix = menuPermPrefix
  currEditData.remark = remark
  currEditData.children = children
}

const onFinishFailed = (errorInfo: any) => {
  console.log('Failed:', errorInfo);
};

//当前选中行
const selectedRows = ref<Key[]>([])
const onSelectChange = (selectedRowKeys: Key[]) => {
  selectedRows.value = selectedRowKeys;
};

const checkParentMenuId = (_rule: Rule, value: string) => {
  if (value == currEditData.menuId?.toString()) {
    return Promise.reject('不能设置自己为父菜单');
  } else {
    return Promise.resolve();
  }
}

//新增相关
const currAddData = ref<SysMenu>({
  menuName: '',
  parentId: 0,
  orderNum: 1,
  path: '',
  component: '',
  query: '',
  isFrame: 1,
  isCache: 1,
  menuType: 'M',
  visible: '0',
  status: '0',
  icon: '',
  menuPermPrefix: '',
  remark: '',
})

const addPopShow = ref(false)
const addApiLoading = ref(false)

const handleAddOk = async () => {
  try {
    addApiLoading.value = true
    if (currAddData.value.menuType === 'B') {
      currAddData.value.menuPermPrefix = ''
    }
    const { data: res }: { data: CrudBack } = await addMenu(currAddData.value)
    if (res.code == 200) {
      getDatas()
      message.success('新增成功')
      addPopShow.value = false
      //清掉
      currAddData.value = {
        menuName: '',
        parentId: 0,
        orderNum: 1,
        path: '',
        component: '',
        query: '',
        isFrame: 1,
        isCache: 1,
        menuType: 'M',
        visible: '0',
        status: '0',
        icon: '',
        menuPermPrefix: '',
        remark: '',
      }
    }
  } catch (error) {

  } finally {
    addApiLoading.value = false
  }
}

const onAddFinishFailed = (errorInfo: any) => {
  console.log('Failed:', errorInfo);
};

const handleAddData = () => {
  addPopShow.value = true
}

const tableStyle = reactive<{
  width: number;
  height: number;
}>({
  width: 300,
  height: 300,
});

onMounted(() => {
  getDatas()
  tableStyle.height = (contentBoxRef.value?.clientHeight as number) - 200;
  tableStyle.width = contentBoxRef.value?.clientWidth as number;
})
</script>
<template>
  <div class="box-border relative h-full p-3" ref="contentBoxRef" :style="{ width: globalStore.isMobile ? 'calc(100% - 60px)' : '100%' }">
    <a-row>
      <a-col :span="24">
        <a-space class="flex flex-wrap">
          <a-button type="ghost"
            class="flex items-center text-white bg-green-500 hover:bg-green-400 hover:border-green-400 "
            :icon="h(antIcons['PlusOutlined'])" @click="handleAddData" :loading="isLoading">新增</a-button>
          <a-button class="flex items-center justify-center" :icon="h(antIcons['ReloadOutlined'])" shape="circle"
            @click="reloadData"></a-button>
          <a-button type="primary" class="flex items-center" danger :icon="h(antIcons['CloseOutlined'])"
            :disabled="selectedRows.length == 0" @click="deleteBatchData">删除</a-button>
        </a-space>
      </a-col>
    </a-row>
    <!-- 表格 -->
    <div class="mt-3  h-fit max-h-[647px]">
      <a-table :columns="columns" :data-source="data" :pagination="false" :loading="isLoading"
        :scroll="{ y: tableStyle.height, x: globalStore.isMobile ? 'calc(100% + 800px)' : '100%' }"
        :row-selection="{ selectedRowKeys: selectedRows, onChange: onSelectChange }">
        <template #bodyCell="{ column, text }">
          <template v-if="column.dataIndex === 'businessType'">
            <p>{{ text == '1' ? '新增' : text == '2' ? '修改' : text == '3' ? '删除' : '其他' }}</p>
          </template>
          <template v-if="column.dataIndex === 'operatorType'">
            <p>{{ text == '1' ? '后台用户' : text == '2' ? '手机用户' : '其他' }}</p>
          </template>
          <template v-if="column.dataIndex === 'status'">
            <a-switch :checked="text === '0'" disabled>
              <template #checkedChildren>
                <CheckOutlined />
              </template>
              <template #unCheckedChildren>
                <CloseOutlined />
              </template>
            </a-switch>
          </template>
          <template v-if="column.dataIndex === 'accessTime'">
            <p>{{ text }}</p>
          </template>
          <template v-if="column.dataIndex === 'icon'">
            <component :is="antIcons[text]"></component>
          </template>
          <template v-if="column.key === 'operation'">
            <a-space>
              <a-button type="primary" class="flex items-center bg-primary-2" size="small"
                @click="editData(text)">编辑</a-button>
              <a-popconfirm :title="`确定删除${text.menuName}吗?`" ok-text="确认" cancel-text="取消"
                @confirm="deleteData($event, text.menuId)">
                <a-button size="small" type="primary" danger class="flex items-center text-white ">删除</a-button>
              </a-popconfirm>
            </a-space>
          </template>
        </template>
      </a-table>
    </div>

    <!-- 修改modal -->
    <a-modal v-model:open="editPopShow" title="修改菜单" :footer="null" width="700px">
      <a-form :model="currEditData" name="currEditData" @finish="handleEditOk" class="mt-5"
        @finishFailed="onFinishFailed" v-bind="{
        labelCol: { span: 3 },
        wrapperCol: { span: 24 },
      }">
        <a-row :gutter="12">
          <a-col :span="12">
            <a-form-item name="menuName" label="菜单名称" :rules="[{ required: true }]" :labelCol="{
        span: 6
      }">
              <a-input v-model:value="currEditData.menuName" placeholder="菜单名称" />
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item name="parentId" label="父菜单" :rules="[{ required: true, validator: checkParentMenuId }]"
              :labelCol="{
        span: 6
      }">
              <a-tree-select v-model:value="currEditData.parentId" show-search style="width: 100%"
                :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" placeholder="请选择父菜单" allow-clear
                tree-default-expand-all :tree-data="fatherMenu" :defaultValue="currEditData.parentId"
                tree-node-filter-prop="label">
                <template #title="{ value: val, label }">
                  <b v-if="val === 'parent 1-1'" style="color: #08c">sss</b>
                  <template v-else>{{ label }}</template>
                </template>
              </a-tree-select>
            </a-form-item>
          </a-col>
        </a-row>
        <a-row :gutter="12">
          <a-col :span="12">
            <a-form-item name="orderNum" label="显示顺序" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-input-number v-model:value="currEditData.orderNum" />
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item name="path" label="路由地址" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-input v-model:value="currEditData.path" placeholder="菜单目录加/" />
            </a-form-item>
          </a-col>
        </a-row>
        <a-row :gutter="12">
          <a-col :span="12">
            <a-form-item name="component" label="路由组件" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-input v-model:value="currEditData.component" placeholder="请输入路由组件" />
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item name="query" label="路由参数" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-input v-model:value="currEditData.query" placeholder="请输入路由参数" />
            </a-form-item>
          </a-col>
        </a-row>
        <a-row :gutter="12">
          <a-col :span="12">
            <a-form-item name="isFrame" label="外链" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-radio-group v-model:value="currEditData.isFrame" :options="[
        { label: '是', value: 0 },
        { label: '否', value: 1 },
      ]" />
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item name="isCache" label="缓存" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-radio-group v-model:value="currEditData.isCache" :options="[
        { label: '是', value: 0 },
        { label: '否', value: 1 },
      ]" />
            </a-form-item>
          </a-col>
        </a-row>
        <a-row :gutter="12">
          <a-col :span="12">
            <a-form-item name="menuType" label="菜单类型" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-radio-group v-model:value="currEditData.menuType" :options="[
        { label: '菜单', value: 'M' },
        { label: '按钮', value: 'B' },
      ]" />
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item name="visible" label="菜单可见" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-radio-group v-model:value="currEditData.visible" :options="[
        { label: '可见', value: '0' },
        { label: '隐藏', value: '1' },
      ]" />
            </a-form-item>
          </a-col>
        </a-row>
        <a-form-item name="icon" label="菜单图标" :rules="[{ required: false }]">
          <a-select v-model:value="currEditData.icon" style="width: 100%" placeholder="选择菜单图标"
            option-label-prop="children" show-search>
            <a-select-option :value="icon" :label="icon" v-for="icon in IconOption">
              <component :is="antIcons[icon]" />
              <span class="ml-3">{{ icon }}</span>
            </a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item name="menuPermPrefix" label="权限前缀" :rules="[{ required: false }]"
          v-if="currEditData.menuType === 'B'">
          <a-input v-model:value="currEditData.menuPermPrefix" />
        </a-form-item>
        <a-form-item name="remark" label="备注" :rules="[{ required: false }]">
          <a-input v-model:value="currEditData.remark" placeholder="备注" />
        </a-form-item>
        <a-form-item name="status" label="菜单状态" :rules="[{ required: false }]">
          <a-switch v-model:checked="currEditData.status" checkedValue="0" unCheckedValue="1">
            <template #checkedChildren>
              <CheckOutlined />
            </template>
            <template #unCheckedChildren>
              <CloseOutlined />
            </template>
          </a-switch>
        </a-form-item>
        <a-form-item :wrapper-col="{
        offset: 19,
        span: 5
      }">
          <a-space>
            <a-button key="back" @click="editPopShow = false">取消</a-button>
            <a-button html-type="submit" type="primary" class="bg-primary-2" :loading="editApiLoading">修改</a-button>
          </a-space>
        </a-form-item>
      </a-form>
    </a-modal>

    <!-- 新增modal -->
    <a-modal v-model:open="addPopShow" title="新增菜单" :footer="null" width="700px">
      <a-form :model="currAddData" name="currAddData" @finish="handleAddOk" class="mt-5"
        @finishFailed="onAddFinishFailed" v-bind="{
        labelCol: { span: 3 },
        wrapperCol: { span: 24 },
      }">
        <a-row :gutter="12">
          <a-col :span="12">
            <a-form-item name="menuName" label="菜单名称" :rules="[{ required: true }]" :labelCol="{
        span: 6
      }">
              <a-input v-model:value="currAddData.menuName" placeholder="菜单名称" />
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item name="parentId" label="父菜单" :rules="[{ required: true, validator: checkParentMenuId }]"
              :labelCol="{
        span: 6
      }">
              <a-tree-select v-model:value="currAddData.parentId" show-search style="width: 100%"
                :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" placeholder="请选择父菜单" allow-clear
                tree-default-expand-all :tree-data="fatherMenu" :defaultValue="currAddData.parentId"
                tree-node-filter-prop="label">
                <template #title="{ label }">
                  <p>{{ label }}</p>
                </template>
              </a-tree-select>
            </a-form-item>
          </a-col>
        </a-row>
        <a-row :gutter="12">
          <a-col :span="12">
            <a-form-item name="orderNum" label="显示顺序" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-input-number v-model:value="currAddData.orderNum" />
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item name="path" label="路由地址" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-input v-model:value="currAddData.path" placeholder="菜单目录加/" />
            </a-form-item>
          </a-col>
        </a-row>
        <a-row :gutter="12">
          <a-col :span="12">
            <a-form-item name="component" label="路由组件" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-input v-model:value="currAddData.component" placeholder="请输入路由组件" />
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item name="query" label="路由参数" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-input v-model:value="currAddData.query" placeholder="请输入路由参数" />
            </a-form-item>
          </a-col>
        </a-row>
        <a-row :gutter="12">
          <a-col :span="12">
            <a-form-item name="isFrame" label="外链" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-radio-group v-model:value="currAddData.isFrame" :options="[
        { label: '是', value: 0 },
        { label: '否', value: 1 },
      ]" />
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item name="isCache" label="缓存" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-radio-group v-model:value="currAddData.isCache" :options="[
        { label: '是', value: 0 },
        { label: '否', value: 1 },
      ]" />
            </a-form-item>
          </a-col>
        </a-row>
        <a-row :gutter="12">
          <a-col :span="12">
            <a-form-item name="menuType" label="菜单类型" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-radio-group v-model:value="currAddData.menuType" :options="[
        { label: '菜单', value: 'M' },
        { label: '按钮', value: 'B' },
      ]" />
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item name="visible" label="菜单可见" :rules="[{ required: false }]" :labelCol="{
        span: 6
      }">
              <a-radio-group v-model:value="currAddData.visible" :options="[
        { label: '可见', value: '0' },
        { label: '隐藏', value: '1' },
      ]" />
            </a-form-item>
          </a-col>
        </a-row>
        <a-form-item name="icon" label="菜单图标" :rules="[{ required: false }]">
          <a-select v-model:value="currAddData.icon" style="width: 100%" placeholder="选择菜单图标"
            option-label-prop="children" show-search>
            <a-select-option :value="icon" :label="icon" v-for="icon in IconOption">
              <component :is="antIcons[icon]" />
              <span class="ml-3">{{ icon }}</span>
            </a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item name="menuPermPrefix" label="权限前缀" :rules="[{ required: false }]"
          v-if="currAddData.menuType === 'B'">
          <a-input v-model:value="currAddData.menuPermPrefix" />
        </a-form-item>
        <a-form-item name="remark" label="备注" :rules="[{ required: false }]">
          <a-input v-model:value="currAddData.remark" placeholder="备注" />
        </a-form-item>
        <a-form-item name="status" label="菜单状态" :rules="[{ required: false }]">
          <a-switch v-model:checked="currAddData.status" checkedValue="0" unCheckedValue="1">
            <template #checkedChildren>
              <CheckOutlined />
            </template>
            <template #unCheckedChildren>
              <CloseOutlined />
            </template>
          </a-switch>
        </a-form-item>
        <a-form-item :wrapper-col="{
        offset: 19,
        span: 5
      }">
          <a-space>
            <a-button key="back" @click="addPopShow = false">取消</a-button>
            <a-button html-type="submit" type="primary" class="bg-primary-2" :loading="addApiLoading">新增</a-button>
          </a-space>
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<style scoped></style>